<%-- Copyright (c) 2010 Canadensys --%>
<%-- JSP container for processing name.ftl page --%>
<%-- TODO : move logic related scriptlet to jar --%>

<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Vector" %>
<%@ page import="net.canadensys.dataportal.vascan.Distribution" %>
<%@ page import="net.canadensys.dataportal.vascan.Habit" %>
<%@ page import="net.canadensys.dataportal.vascan.Lookup" %>
<%@ page import="net.canadensys.dataportal.vascan.Taxon" %>
<%@ page import="net.canadensys.dataportal.vascan.TaxonManager" %>
<%@ page import="net.canadensys.dataportal.vascan.VernacularName" %>
<%@ page import="net.canadensys.dataportal.vascan.VernacularNameManager" %>
<%@ page import="net.canadensys.dataportal.vascan.utils.LabelMappings" %>
<%@ page import="net.canadensys.dataportal.vascan.predicates.*" %>
<%@ page import="net.canadensys.dataportal.utils.*" %>
<%@ page import="org.apache.commons.collections.iterators.FilterIterator" %>
<%@ include file="_inc/functions.jsp" %>
<%  String TEMPLATE_PATH = "name.ftl"; %>
<%@ include file="_inc/ftl/processStart.jsp" %>
<%
try{
    /* 
     * Name hub ;
     * This page will display all available information for a taxon OR for a
     * vernacular name;
     * in the case where :
    	 we have many match for a vernacular name,
    	 we have multiple taxon for a given name (accepted, synonym, source)
     * we need to display the disambiguation page
     */
    
    // request name parameter in url
    String name = "";
    if(request.getParameter("name") != null)
        name = request.getParameter("name");
    
    String pageTitle = name;
    String nameH1 = name;
    
    // request redirect parameter in url
    String redirect = "";
    if(request.getParameter("redirect") != null)
        redirect = request.getParameter("redirect");
   
    // is the name param for a vernacular name
    boolean isVernacularName = false;
    // should we display a warning saying this is a vernacular name of something
    boolean isVernacularNameWarning = false;
    String vernacularNameWarning = "";
    int vernacularNameWarningId = 0;
    String vernacularNameWarningStatus = "";
    String vernacularNameWarningLanguage = "";
    String vernacularNameWarningReference = "";
    String vernacularNameWarningReferenceShort = "";
    String vernacularNameWarningLink = "";
    
    // should we stop the redirect
    boolean isRedirect = true;
    if(redirect.equals(new String("no")))
        isRedirect = false;
    
    // is the name param for a taxon
    boolean isTaxon = false;
    // should we display a warning saying this is a synonym of something
    boolean isSynonym = false;
    boolean isSynonymWarning = false;
    String synonymWarning = "";
    String synonymWarningUrl = "";
    String synonymWarningH1 = "";
    String synonymWarningReference = "";
    String synonymWarningReferenceShort = "";
    String synonymWarningLink = "";
    int synonymWarningId = 0;

    // is he taxon concept an hybrid
    // the state of isHybridConcept is determined by inspecting the taxon
    // full scientific name for the presence of "x" (multiply sign); this
    // is acheived by the method isHybird() in Taxon; The hybrid status
    // cannot be determined by the presence of hybrid parents because
    // they are sometimes unknown (no entry in database for hybdridparent1 and
    // hybridparent1, but we know that it's an hybrid, because someone said so.
    boolean isHybrid = false;
    
    // does this page requires disambiguation
    boolean requiresDisambiguation = false;
 
    // taxons 
    List<Taxon> taxons = new ArrayList<Taxon>();
    
    /*
     * the following vars are containers that will receive the related taxon
     * for all name
     *
     */
    List<Taxon> nameTaxons = null;
    
    /*
     * the following vars are containers that will receive the related taxon
     * for all vernacular name 
     */
    VernacularName vernacularName = null;
    List<VernacularName> vernacularNames = null;
    List<Taxon> vernacularTaxons = new ArrayList<Taxon>();


    // disambiguation vernacular concept container
    Vector<HashMap<String,Object>> disambiguationVernaculars = new Vector<HashMap<String,Object>>();
    // disambiguation taxons container
    Vector<HashMap<String,Object>> disambiguationTaxons = new Vector<HashMap<String,Object>>();

    // single taxon concept 
    Taxon taxon = null;
    
    // id
    int id = 0;
    
    // status 
    String status = "";
 
    // rank
    String rank = "";
    String rankfr = "";
    
    // rankid
    int rankid = 0;
    
    // reference code
    String reference = "";

    // reference short
    String referenceShort = "";
    
    // reference link
    String link = "";
    
    boolean computedDistribution = false;
    
    // is taxon is an accepted concept, verify if it's distribution image exists
    // if not, create the svg & png file. Never create a distribution image file
    // for a synonym
    String png = "";
    String svg = "";
    
    // data hashmap that will be passed on to root document for display in .ftl
    HashMap<String,Object> data = new HashMap<String,Object>();
    
    // content vectors (propety store for object passed to the ftl)
    Vector<HashMap<String,Object>> taxonHybridParents = new Vector<HashMap<String,Object>>();
    Vector<HashMap<String,Object>> taxonParents = new Vector<HashMap<String,Object>>();
    Vector<HashMap<String,Object>> taxonClassification = new Vector<HashMap<String,Object>>();
    Vector<HashMap<String,Object>> taxonVernacularNames = new Vector<HashMap<String,Object>>();
    Vector<HashMap<String,Object>> taxonSynonyms = new Vector<HashMap<String,Object>>();
    Vector<HashMap<String,Object>> taxonHabituses = new Vector<HashMap<String,Object>>();
    Vector<HashMap<String,Object>> taxonDistributions = new Vector<HashMap<String,Object>>();
    
    vernacularNames = VernacularNameManager.findByName(name);
    // for a given vernacular name, try to find all the related taxons
   
    if(vernacularNames != null){
        //get all concepts attached to a vernacular name and add all taxons
        

        for(VernacularName vernacular : vernacularNames){
            vernacularTaxons.add(vernacular.getTaxon());
        }
   		if(vernacularTaxons != null){
	        if(vernacularTaxons.size() > 1){
	        	isVernacularName = true;
	            requiresDisambiguation = true;
	        }
	        else if(vernacularTaxons.size() == 1){
	        	isVernacularName = true;
	            isVernacularNameWarning = true;
	            vernacularNameWarning = vernacularNames.get(0).getName().trim();
	            vernacularNameWarningId = vernacularNames.get(0).getId();
	            vernacularNameWarningStatus = vernacularNames.get(0).getStatus().getStatus();
	            vernacularNameWarningLanguage = vernacularNames.get(0).getLanguage();
	            vernacularNameWarningReference = vernacularNames.get(0).getReference().getReference();
	            vernacularNameWarningReferenceShort = vernacularNames.get(0).getReference().getReferenceshort();
	            vernacularNameWarningLink = vernacularNames.get(0).getReference().getUrl();
	        	taxon = vernacularTaxons.get(0);
	        	
                if(redirect.equals(new String("no"))){
                    pageTitle = vernacularNames.get(0).getName();
                }
	        }
	    }
    }
    
    // for a given name, try to find all the ralated taxons
    nameTaxons = TaxonManager.findByName(name);
   	if(nameTaxons != null){
        if(nameTaxons.size() > 1){
            isTaxon = true;
            requiresDisambiguation = true;
        }
        else if(nameTaxons.size() == 1){
        	taxon = (Taxon)nameTaxons.get(0);
            // if this is a synonym concept, we need to find the accepted parent of this taxon
            // to display on the page. In the extreamly rare case where a synonym taxon has more
            // than one parent, we need to go to disambiguation.
            if(taxon.getStatus().getId() == ApplicationConfig.STATUS_SYNONYM){
            	isSynonymWarning = true;
            	isSynonym = true;
            	synonymWarning = taxon.getLookup().getCalnamehtmlauthor();
            	synonymWarningUrl = taxon.getLookup().getCalname();
            	synonymWarningH1 = taxon.getLookup().getCalnamehtml();
            	synonymWarningId = taxon.getId();
                synonymWarningReference = taxon.getReference().getReference();
                synonymWarningReferenceShort = taxon.getReference().getReferenceshort();
                synonymWarningLink = taxon.getReference().getUrl();
            	
            	
            	if(taxon.getParents() != null && taxon.getParents().size() > 1){
           			isTaxon = true;
          			requiresDisambiguation = true;
            	}
           		else if(taxon.getParents() != null && taxon.getParents().size()  == 1){
      			    isTaxon = true;
      			    nameTaxons = taxon.getParents();
      			    taxon = nameTaxons.get(0);
            	}
            	
            	
            	if(redirect.equals(new String("no"))){
                    pageTitle = taxon.getLookup().getCalname();
                }
                
            	
            }
            else{
                isTaxon = true;
            }
        }
    }
   	
   	// is a vernacular name shares a name with a taxon ; automatic disambiguation
   	if(isTaxon && isVernacularName){
   		requiresDisambiguation = true;
   	}

    // raise error if name param is not a taxon and not a vernacular name 
    if(!isTaxon && !isVernacularName){
    	notFound(response);
    }
    else if(requiresDisambiguation){
        if(isVernacularName){
   		    for(VernacularName vernacular : vernacularNames){
   		    	HashMap<String,Object> vernacularDisambiguation = new HashMap<String,Object>();
   		    	Vector<HashMap<String,Object>> vernacularConceptsTaxons = new Vector<HashMap<String,Object>>();
   		    	// base discriminating vernacular info : name, source, status, language
   		    	vernacularDisambiguation.put("vernacularid",vernacular.getId());
   		    	vernacularDisambiguation.put("name",vernacular.getName());
   		    	vernacularDisambiguation.put("reference",vernacular.getReference().getReference());
   		    	vernacularDisambiguation.put("referenceShort",vernacular.getReference().getReferenceshort());
   		    	vernacularDisambiguation.put("link",vernacular.getReference().getUrl());
   		    	vernacularDisambiguation.put("language",vernacular.getLanguage());
   		    	vernacularDisambiguation.put("status",vernacular.getStatus().getStatus());
   		    	// taxon concept
   		    	HashMap<String,Object> t = new HashMap<String,Object>();
   		    	t.put("taxonId",vernacular.getTaxon().getId());
   		    	t.put("fullScientificName",vernacular.getTaxon().getLookup().getCalnamehtmlauthor());
   		    	t.put("reference",vernacular.getTaxon().getReference().getReference());
   		    	t.put("referenceShort",vernacular.getTaxon().getReference().getReferenceshort());
   		    	t.put("link",vernacular.getTaxon().getReference().getUrl());
   		    	t.put("status",vernacular.getTaxon().getStatus().getStatus());
   		    	t.put("rank",vernacular.getTaxon().getRank().getRank());
   		    	vernacularDisambiguation.put("taxon",t);
   		    	disambiguationVernaculars.add(vernacularDisambiguation);
   		    }
    	}
    	
    	if(isTaxon){    				
    		if(!redirect.equals(new String("no")))
    			  pageTitle = TaxonManager.findByName(name).get(0).getLookup().getCalname();
            nameH1 = TaxonManager.findByName(name).get(0).getLookup().getCalnamehtml();

            for(Taxon taxonConcept : nameTaxons){
                HashMap<String,Object> taxonDisambiguation = new HashMap<String,Object>();
                Vector<HashMap<String,Object>> taxonDisambiguationParents = new Vector<HashMap<String,Object>>();
                taxonDisambiguation.put("taxonId",taxonConcept.getId());
                
                taxonDisambiguation.put("fullScientificName",taxonConcept.getLookup().getCalnamehtmlauthor());
                taxonDisambiguation.put("reference",taxonConcept.getReference().getReference());
                taxonDisambiguation.put("referenceShort",taxonConcept.getReference().getReferenceshort());
                taxonDisambiguation.put("link",taxonConcept.getReference().getUrl());
                taxonDisambiguation.put("status",taxonConcept.getStatus().getStatus());
                taxonDisambiguation.put("rank",taxonConcept.getRank().getRank());
                
                List<Taxon> parents = taxonConcept.getParents();
                for(Taxon parent : parents){
                	HashMap<String,Object> taxonParent = new HashMap<String,Object>();
                	taxonParent.put("taxonId",parent.getId());
                    taxonParent.put("fullScientificName",parent.getLookup().getCalnamehtmlauthor());
                    taxonParent.put("reference",parent.getReference().getReference());
                    taxonParent.put("referenceShort",parent.getReference().getReferenceshort());
                    taxonParent.put("link",parent.getReference().getUrl());
                    taxonParent.put("status",parent.getStatus().getStatus());
                    taxonParent.put("rank",parent.getRank().getRank());
                    taxonDisambiguationParents.add(taxonParent);
                }
                
                taxonDisambiguation.put("parents",taxonDisambiguationParents);
                
                disambiguationTaxons.add(taxonDisambiguation);
            }
    	}
    }
    else{
    	// id
    	id =  taxon.getId();
    	
    	// fullscientific name
        name = taxon.getLookup().getCalnamehtmlauthor();

    	if(!redirect.equals(new String("no"))){
	       pageTitle = taxon.getLookup().getCalname();
    	}
        
        nameH1 = taxon.getLookup().getCalnamehtml();
        
        // status
        status = taxon.getStatus().getStatus();
        
        
        // rank
        rank = taxon.getRank().getRank();

        // rankid
        rankid = taxon.getRank().getId();
        
        // refrence 
        reference = taxon.getReference().getReference();

        // refrenceShort
        referenceShort = taxon.getReference().getReferenceshort();
        
        // link 
        link = taxon.getReference().getUrl();
        
        // hybrid parents
        List<Taxon> hybridParents = null;
        hybridParents = taxon.getHybridparents();
        
        if(hybridParents != null){
            if(hybridParents.size() > 0)
                isHybrid = true;
            for(Taxon hybridParent : hybridParents){
                HashMap<String,Object> hybridParentInfo = new HashMap<String,Object>();
                try{
                	hybridParentInfo.put("taxonId",hybridParent.getId());
                	hybridParentInfo.put("fullScientificName",hybridParent.getLookup().getCalnamehtmlauthor());
                    hybridParentInfo.put("status",hybridParent.getStatus().getStatus());
                    taxonHybridParents.add(hybridParentInfo);
                }
                catch(NullPointerException e){
                    //drop on error
                }
            }
        }
        
        // parents ; it is accepted that a taxon has only one parent, but this
        // is not a rule and some exceptions may occur with synonyms. To prevent
        // errors, the getParent() method of a txon returns a list of most of 
        // the time one element...
        List<Taxon> parents= null;
        parents = taxon.getParents();
        if(parents != null){
            for(Taxon parent : parents){
                HashMap<String,Object> parentInfo = new HashMap<String,Object>();
                try{
                    parentInfo.put("fullScientificName",parent.getLookup().getCalnamehtmlauthor());
                    taxonParents.add(parentInfo);
                }
                catch(NullPointerException e){
                    //drop on error
                }
            }
        }
        
        // classification for taxon ; get all the hierarchy of taxon above, and possibly
        // below of taxon, and save to hashmap and add to vector. Vector is available
        // as a sequence in .ftl
        List<Taxon> classification = null;
        classification = TaxonManager.getClassification(taxon);
        if(classification != null){
            for(Taxon node : classification){
                HashMap<String,Object> nodeInfo = new HashMap<String,Object>();
                try{
                	nodeInfo.put("taxonId",node.getId());
                	nodeInfo.put("fullScientificName",node.getLookup().getCalnamehtml());
                    nodeInfo.put("rank",node.getRank().getRank());
                    nodeInfo.put("rankId",node.getRank().getId());
                    taxonClassification.add(nodeInfo);
                }
                catch(NullPointerException e){
                    //drop on error
                    //TODO: an here is should raise concerns, display a message ?
                }
            }
        }
        
        // vernacular names for taxon ; each vernacular name is saved in an hashmap
        // and all hashmap are added to a vector wich is added to the main data 
        // hashmap. That vector is available in the ftl as a sequence
        vernacularNames = taxon.getVernacularnames();
        if(vernacularNames != null){
            for(VernacularName vernacular : vernacularNames){
                try{
                    HashMap<String,Object> vernacularData = new HashMap<String,Object>();
                    vernacularData.put("vernacularId",vernacular.getId());
                    vernacularData.put("name",vernacular.getName());
                    vernacularData.put("status",vernacular.getStatus().getStatus());
                    vernacularData.put("language",vernacular.getLanguage());
                    vernacularData.put("reference",vernacular.getReference().getReference());
                    vernacularData.put("referenceShort",vernacular.getReference().getReferenceshort());
                    vernacularData.put("link",vernacular.getReference().getUrl());
                    taxonVernacularNames.add(vernacularData);
                }
                catch(NullPointerException e){
                    //out.write(e.toString());
                }
            }
        }
        
        // synonyms for taxon ; each synonym is saved in an hashmap and all hashmap
        // are added to a vector wich is added to the main data hashmap. That vector
        // is available in the ftl as a sequence. The synonyms are filtered from the
        // children of the taxon by the isSynonymPredicate predicate
        List<Taxon> synonyms = null;
        FilterIterator filterIterator = new FilterIterator(taxon.getChildren().iterator(),new IsSynonymPredicate());
        if(filterIterator != null){
            while(filterIterator.hasNext()){
                try{
                    HashMap<String,Object> synonymData = new HashMap<String,Object>();
                    Taxon synonym = (Taxon) filterIterator.next();
                    synonymData.put("taxonId",synonym.getId());
                    synonymData.put("fullScientificName",synonym.getLookup().getCalnamehtmlauthor());
                    synonymData.put("fullScientificNameUrl",synonym.getLookup().getCalname());
                    synonymData.put("reference",synonym.getReference().getReference());
                    synonymData.put("referenceShort",synonym.getReference().getReferenceshort());
                    synonymData.put("link",synonym.getReference().getUrl());
                    taxonSynonyms.add(synonymData);
                }
                catch(NullPointerException e){
                    //drop on error
                    
                }
            }
        }

        
        // habitus
        List<Habit> habituses;
        habituses = taxon.getHabit();
        if(habituses != null){
            for(Habit habitus : habituses){
                try{
                    HashMap<String,Object> habitusData = new HashMap<String,Object>();  
                    habitusData.put("habitus",habitus.getHabit());
                    taxonHabituses.add(habitusData);
                }
                catch(NullPointerException e){
                    //drop on error
                }
            }
        }
     
        // distribution
        List<Distribution> distributions;
        distributions = taxon.getDistribution();
        if(distributions != null){
            for(Distribution distribution : distributions){
                try{
                    HashMap<String,Object> distributionData = new HashMap<String,Object>();
                    distributionData.put("province",distribution.getRegion().getRegion());
                    distributionData.put("status",distribution.getDistributionStatus().getDistributionstatus());
                    distributionData.put("excluded",distribution.getExcludedcode().getExcludedcode());
                    distributionData.put("reference",distribution.getReference().getReference());
                    distributionData.put("referenceShort",distribution.getReference().getReferenceshort());
                    distributionData.put("link",distribution.getReference().getUrl());
                    taxonDistributions.add(distributionData);
                }
                catch(NullPointerException e){
                    //drop on error
                    e.printStackTrace();
                }
            }
        }
        
        // if taxon has no distribution information (distribution entity), display
        // distribution lookup info (distributionlookup entity) and display message
        // to user...
        if(taxonDistributions.size() == 0){
            computedDistribution = true;
            //build a distribution hashmap and add to taxonDistributions vector
            Lookup lookup = taxon.getLookup();
            if(lookup != null)
            	taxonDistributions = TaxonManager.computeDistribution(lookup);
        }
        
        //if(!isSynonym){
	        svg = ApplicationConfig.getGeneratedImageURL() + ApplicationConfig.SVG_FILE_PREFIX + taxon.getId() + ApplicationConfig.SVG_FILE_EXT;
	        png = ApplicationConfig.getGeneratedImageURL() + ApplicationConfig.SVG_FILE_PREFIX + taxon.getId() + ApplicationConfig.PNG_FILE_EXT;
        //}           
    }
    
    data.put("taxonId",id);
    
    data.put("requiresDisambiguation",requiresDisambiguation);
    data.put("isRedirect",isRedirect);
    data.put("isTaxon",isTaxon);
    data.put("id",id);
    data.put("name",name);
    data.put("pageTitle",pageTitle);
    data.put("nameH1",nameH1);
    
    data.put("isSynonym",isSynonym);
    data.put("isSynonymWarning",isSynonymWarning);
    data.put("synonymWarning",synonymWarning);
    data.put("synonymWarningUrl",synonymWarningUrl);
    data.put("synonymWarningH1",synonymWarningH1);
    data.put("synonymWarningId",synonymWarningId);
    data.put("synonymWarningReference",synonymWarningReference);
    data.put("synonymWarningReferenceShort",synonymWarningReferenceShort);
    data.put("synonymWarningLink",synonymWarningLink);
    data.put("isVernacularName",isVernacularName);
    data.put("isVernacularNameWarning",isVernacularNameWarning);
    data.put("vernacularNameWarning",vernacularNameWarning);
    data.put("vernacularNameWarningId",vernacularNameWarningId);
    data.put("vernacularNameWarningStatus",vernacularNameWarningStatus);
    data.put("vernacularNameWarningLanguage",vernacularNameWarningLanguage);
    data.put("vernacularNameWarningReference",vernacularNameWarningReference);
    data.put("vernacularNameWarningReferenceShort",vernacularNameWarningReferenceShort);
    data.put("vernacularNameWarningLink",vernacularNameWarningLink);
    data.put("status",status);
    data.put("reference",reference);
    data.put("referenceShort",referenceShort);
    data.put("link",link);
    data.put("isHybridConcept",isHybrid);
    data.put("rank",rank);
    data.put("rankId",rankid);
    data.put("png",png);
    data.put("svg",svg);
    data.put("pngDownload",png+ApplicationConfig.DOWNLOAD_GENERATED_IMG_URL);
    data.put("svgDownload",svg+ApplicationConfig.DOWNLOAD_GENERATED_IMG_URL);
    
    data.put("disambiguationVernaculars",disambiguationVernaculars);
    data.put("disambiguationTaxons",disambiguationTaxons);
    data.put("hybridParents",taxonHybridParents);
    data.put("parents",taxonParents);
    data.put("tree",taxonClassification);
    data.put("vernacularNames",taxonVernacularNames);
    data.put("synonyms",taxonSynonyms);
    data.put("habituses",taxonHabituses);
    data.put("computedDistribution",computedDistribution);
    data.put("distributions",taxonDistributions);

    // attach data to document root
    root.put("data",data);
    
    // add extra data to page global hashmap
    _page.put("rank",LabelMappings.getRankLabel(rankid));
    _page.put("isDisambiguation",requiresDisambiguation);
    _page.put("isVernacular",isVernacularName);
    _page.put("isSynonym",isSynonym);
    
}
catch(org.hibernate.ObjectNotFoundException e){
    //notFound(response);
    e.printStackTrace();
    out.write(e.toString());
}
catch(Exception e){
    out.write("Fatal error : " + e.toString());
    e.printStackTrace();
}
%>
<%@ include file="_inc/ftl/processStop.jsp" %>